package com.ibeeking.found.upms.b.rest.service.impl;

import com.ibeeking.found.common.constants.HeaderNounConstant;
import com.ibeeking.found.common.entity.TenantDTO;
import com.ibeeking.found.common.enums.IndustryTypeEnum;
import com.ibeeking.found.upms.service.common.param.*;
import com.ibeeking.found.common.base.BaseDO;
import com.ibeeking.found.common.config.feign.GlobalClient;
import com.ibeeking.found.common.config.feign.MsgFeignClient;
import com.ibeeking.found.common.config.prop.FileOssProp;
import com.ibeeking.found.common.config.secret.RsaConfig;
import com.ibeeking.found.common.constants.DefaultPathConstant;
import com.ibeeking.found.common.entity.LoginUserDTO;
import com.ibeeking.found.common.entity.UserInfoDTO;
import com.ibeeking.found.common.enums.LoginRoleEnum;
import com.ibeeking.found.common.enums.PublishStatusEnum;
import com.ibeeking.found.common.enums.SexEnum;
import com.ibeeking.found.common.enums.member.MemberSexEnum;
import com.ibeeking.found.common.utils.UrlUtils;
import com.ibeeking.found.common.utils.UserUtils;
import com.ibeeking.found.id.GenerateId;
import com.ibeeking.found.upms.api.common.dto.TenantListDTO;
import com.ibeeking.found.upms.api.common.dto.TenantUserDTO;
import com.ibeeking.found.upms.api.common.query.AccountLoginQuery;
import com.ibeeking.found.upms.api.feign.GlobalTenantClient;
import com.ibeeking.found.upms.b.rest.config.prop.UserConfigProp;
import com.ibeeking.found.upms.b.rest.service.IShopUserService;
import com.ibeeking.found.upms.b.rest.service.ITenantUserRoleService;
import com.ibeeking.found.upms.b.rest.service.ITenantUserService;
import com.ibeeking.found.upms.service.common.bo.TenantUserBO;
import com.ibeeking.found.upms.service.common.bo.TenantUserRoleBO;
import com.ibeeking.found.upms.service.common.bo.TenantUserRoleInfoBO;
import com.ibeeking.found.upms.service.common.constants.RedisKeyConstant;
import com.ibeeking.found.upms.service.common.dos.ShopUserDO;
import com.ibeeking.found.upms.service.common.dos.TenantUserDO;
import com.ibeeking.found.upms.service.common.po.TenantUserPO;
import com.ibeeking.found.upms.service.common.query.SelectTenantUserQuery;
import com.ibeeking.found.upms.service.common.query.TenantUserPageQuery;
import com.ibeeking.found.upms.service.common.vo.CurrentUserVO;
import com.ibeeking.found.upms.service.common.vo.TenantListVO;
import com.ibeeking.found.upms.service.common.vo.TenantUserVO;
import com.ibeeking.found.upms.service.common.vo.GmcUserPageVO;
import com.ibeeking.found.upms.service.mapper.TenantUserMapper;
import com.ibeeking.nematos.constants.enums.LogClassifyEnum;
import com.ibeeking.nematos.core.utils.SpringBeanUtil;
import com.ibeeking.nematos.exception.BusinessException;
import com.ibeeking.nematos.exception.EncryptException;
import com.ibeeking.nematos.log.utils.LogUtils;
import com.ibeeking.nematos.redis.annotation.CacheEvict;
import com.ibeeking.nematos.utils.bean.BeanUtil;
import com.ibeeking.nematos.utils.data.Collections3;
import com.ibeeking.nematos.utils.data.StringUtils;
import com.ibeeking.nematos.utils.encryption.EncryptUtils;
import com.ibeeking.nematos.utils.json.JsonUtils;
import com.ibeeking.nematos.utils.result.ResponseResult;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName TenantUserServiceImpl
 * @Description 全局用户
 * @Author ibeeking
 * @Date 2020-12-01 18:36
 **/
@Service
public class TenantUserServiceImpl implements ITenantUserService {

    @Resource
    private TenantUserMapper tenantUserMapper;
    @Resource
    private ITenantUserRoleService userRoleServiceImpl;
    @Resource
    private GlobalClient globalClient;
    @Resource
    private MsgFeignClient msgClient;
    @Resource
    private PasswordEncoder passwordEncoder;
    @Resource
    private FileOssProp fileOssProp;
    @Resource
    private UserConfigProp userConfigProp;
    @Resource
    private RsaConfig rsaConfig;
    @Resource
    private GlobalTenantClient globalTenantClient;
    @Resource
    private IShopUserService shopUserServiceImpl;

    @Override
    public Page<GmcUserPageVO> pageList(TenantUserPageQuery query) {
        if (null != query.getCreateStartTime() && null == query.getCreateEndTime()) {
            query.setCreateEndTime(LocalDateTime.now());
        }
        if (null == query.getCreateStartTime() && null != query.getCreateEndTime()) {
            query.setCreateStartTime(LocalDateTime.now());
        }
        LambdaQueryWrapper<TenantUserDO> queryWrapper = new LambdaQueryWrapper<>(TenantUserDO.class);
        queryWrapper.orderByDesc(BaseDO::getCreateTime)
                .eq(null != query.getPublishStatus(), TenantUserDO::getPublishStatus, query.getPublishStatus())
                .eq(null != query.getJob(), TenantUserDO::getJob, query.getJob())
                .eq(null != query.getSex(), TenantUserDO::getSex, query.getSex())
                .like(StringUtils.isNotBlank(query.getName()), TenantUserDO::getName, query.getName())
                .like(StringUtils.isNotBlank(query.getMobile()), TenantUserDO::getMobile, query.getMobile())
                .like(StringUtils.isNotBlank(query.getTel()), TenantUserDO::getTel, query.getTel())
                .like(StringUtils.isNotBlank(query.getEmail()), TenantUserDO::getEmail, query.getEmail())
                .between(null != query.getCreateStartTime(), BaseDO::getCreateTime, query.getCreateStartTime(), query.getCreateEndTime())
        ;
        Page<TenantUserDO> page = tenantUserMapper.selectPage(new Page<>(query.getPageNum(), query.getPageSize()), queryWrapper);
        Page<GmcUserPageVO> result = BeanUtil.convertPage(page, GmcUserPageVO.class);
        Optional.ofNullable(result.getRecords()).ifPresent(list -> {
            List<TenantUserRoleInfoBO> roleByUserIds = userRoleServiceImpl.queryUserRoleByUserIds(list.stream().map(GmcUserPageVO::getId).collect(Collectors.toList()));
            Map<Long, List<TenantUserRoleInfoBO>> groupMap = roleByUserIds.parallelStream().collect(Collectors.groupingBy(TenantUserRoleInfoBO::getUserId));

            list.stream().forEach(userPageVO -> {
                userPageVO.setSexName(MemberSexEnum.getDescByCode(userPageVO.getSex()));
                Optional.ofNullable(userPageVO.getImage()).ifPresent(image -> userPageVO.setImage(UrlUtils.addUrlDomainName(fileOssProp.getHost(), userPageVO.getImage())));
                if (groupMap.containsKey(userPageVO.getId())) {
                    userPageVO.setRoleName(String.join(",", groupMap.get(userPageVO.getId()).stream().map(TenantUserRoleInfoBO::getName).collect(Collectors.toList())));
                }
            });
        });
        return result;
    }

    @Override
    public Boolean add(Integer tenantId, TenantUserParam param) {
        //查询商户端是否已经存在当前手机号
        List<ShopUserDO> shopUserDos = shopUserServiceImpl.queryByMobile(param.getMobile());
        if (!Collections3.isEmpty(shopUserDos)) {
            throw new BusinessException("当前手机号已是商户员工，请删除后再添加到租户");
        }
        TenantUserDO tenantUserDO = BeanUtil.convertBean(param, TenantUserDO.class);
        tenantUserDO.setUserCode(param.getMobile());
        tenantUserDO.setCreateBy(UserUtils.getUserId());
        tenantUserDO.setCreateTime(LocalDateTime.now());
        tenantUserDO.setModifyTime(LocalDateTime.now());
        tenantUserDO.setPublishStatus(PublishStatusEnum.ENABLE.getValue());
        tenantUserDO.setJob(PublishStatusEnum.ENABLE.getValue());
        //查询所有租户是否存在当前手机号用户
        List<TenantUserPO> tenantUserPos = selectAllByMobile(param.getMobile());
        if (Collections3.isEmpty(tenantUserPos)) {
            //新增用户
            tenantUserPos = Collections3.emptyList();
            tenantUserDO.setId(GenerateId.generateId());
            tenantUserDO.setPassword(passwordEncoder.encode(userConfigProp.getInitialPwd()));
            tenantUserDO.setImage(StringUtils.isBlank(param.getImage()) ? DefaultPathConstant.DEFAULT_USER_HEAD_IMAGE : param.getImage());
        } else {
            tenantUserDO.setId(tenantUserPos.get(0).getId());
            tenantUserDO.setPassword(tenantUserPos.get(0).getPassword());
            tenantUserDO.setImage(tenantUserPos.get(0).getImage());
        }
        //查询是否存在
        List<Integer> tenantIds = tenantUserPos.stream().map(TenantUserPO::getTenantId).collect(Collectors.toList());
        if (tenantIds.contains(tenantId)) {
            throw new BusinessException("当前手机号已存在");
        }
        return tenantUserMapper.insert(tenantUserDO) > 0;
    }

    @Override
    public Boolean modify(TenantUserParam param) {
        TenantUserDO tenantUserDO = BeanUtil.convertBean(param, TenantUserDO.class);
        tenantUserDO.setMobile(null);
        tenantUserDO.setModifyBy(UserUtils.getUserId());
        tenantUserDO.setModifyTime(LocalDateTime.now());
        return getBean().modifyData(tenantUserDO, null, true);
    }

    @Override
    public TenantUserVO view(Long id) {
        TenantUserBO tenantUserBO = getBean().queryById(id);
        TenantUserVO tenantUserVO = BeanUtil.convertBean(tenantUserBO, TenantUserVO.class);
        tenantUserVO.setImage(UrlUtils.addUrlDomainName(fileOssProp.getHost(), tenantUserVO.getImage()));
        return tenantUserVO;
    }

    @Override
    public TenantUserBO queryById(Long id) {
        TenantUserDO tenantUserDO = tenantUserMapper.selectById(id);
        return BeanUtil.convertBean(tenantUserDO, TenantUserBO.class);
    }

    @Override
    public Boolean changeStatus(Long id, Integer status, Long userId) {
        if (userId.equals(id)) {
            throw new BusinessException("禁止禁用自己");
        }

        //修改当前租户下状态
        TenantUserDO tenantUserDO = new TenantUserDO();
        tenantUserDO.setId(id);
        tenantUserDO.setPublishStatus(status);
        tenantUserDO.setModifyBy(userId);
        tenantUserDO.setModifyTime(LocalDateTime.now());
        return getBean().modifyData(tenantUserDO, null, false);
    }

    @Deprecated
    @Override
    public Boolean logout(String tenantId, Long userId) {
        List<Integer> tenantIds = null;
        TenantUserDO tenantUserDO = new TenantUserDO();
        tenantUserDO.setId(userId);
        tenantUserDO.setJob(PublishStatusEnum.DISABLE.getValue());
        tenantUserDO.setPublishStatus(PublishStatusEnum.DISABLE.getValue());
        tenantUserDO.setModifyTime(LocalDateTime.now());
        if (StringUtils.isNotBlank(tenantId) && !"null".equalsIgnoreCase(tenantId)) {
            tenantIds = Arrays.asList(Integer.valueOf(tenantId));
        }
        //如果未选中租户，注销全部账号信息，
        return getBean().modifyData(tenantUserDO, tenantIds, true);
    }

    @Override
    public Boolean logout(LogoutUserParam param) {
        Long userId = param.getUserId();
        String tenantId = param.getTenantId();
        phoneCodeCheck(param.getMobile(), param.getVerificationCode(), param.getKey());
        List<Integer> tenantIds = null;
        TenantUserDO tenantUserDO = new TenantUserDO();
        tenantUserDO.setId(userId);
        tenantUserDO.setDescription(param.getDescription());
        tenantUserDO.setJob(PublishStatusEnum.DISABLE.getValue());
        tenantUserDO.setPublishStatus(PublishStatusEnum.DISABLE.getValue());
        tenantUserDO.setModifyTime(LocalDateTime.now());
        if (StringUtils.isNotBlank(tenantId) && !"null".equalsIgnoreCase(tenantId)) {
            tenantIds = Arrays.asList(Integer.valueOf(tenantId));
        }
        //如果未选中租户，注销全部账号信息，
        return getBean().modifyData(tenantUserDO, tenantIds, true);
    }

    @Override
    public List<TenantUserVO> selectList(SelectTenantUserQuery query) {
        LambdaQueryWrapper<TenantUserDO> queryWrapper = new LambdaQueryWrapper<>(TenantUserDO.class);
        queryWrapper.orderByDesc(BaseDO::getCreateTime)
                .eq(null != query.getId(), TenantUserDO::getId, query.getId())
                .eq(TenantUserDO::getPublishStatus, PublishStatusEnum.ENABLE.getValue())
                .eq(null != query.getJob(), TenantUserDO::getJob, query.getJob())
                .eq(null != query.getSex(), TenantUserDO::getSex, query.getSex())
                .eq(StringUtils.isNotBlank(query.getUserCode()), TenantUserDO::getUserCode, query.getUserCode())
                .like(StringUtils.isNotBlank(query.getName()), TenantUserDO::getName, query.getName())
                .like(StringUtils.isNotBlank(query.getMobile()), TenantUserDO::getMobile, query.getMobile())
                .like(StringUtils.isNotBlank(query.getTel()), TenantUserDO::getTel, query.getTel())
                .like(StringUtils.isNotBlank(query.getEmail()), TenantUserDO::getEmail, query.getEmail())
                .eq(TenantUserDO::getJob, PublishStatusEnum.ENABLE.getValue())
        ;
        List<TenantUserDO> tenantUserDos = tenantUserMapper.selectList(queryWrapper);
        List<TenantUserVO> tenantUserVos = JsonUtils.jsonToList(tenantUserDos, TenantUserVO.class);

        Optional.ofNullable(tenantUserVos).ifPresent(list -> {
            list.stream().forEach(userVO -> {
                userVO.setSexName(MemberSexEnum.getDescByCode(userVO.getSex()));
                Optional.ofNullable(userVO.getImage()).ifPresent(image -> userVO.setImage(fileOssProp.getHost().concat(userVO.getImage())));
            });
        });
        return tenantUserVos;
    }

    @Override
    public Boolean quit(Long id) {
        TenantUserDO tenantUserDO = new TenantUserDO();
        tenantUserDO.setId(id);
        tenantUserDO.setJob(PublishStatusEnum.DISABLE.getValue());
        tenantUserDO.setPublishStatus(PublishStatusEnum.DISABLE.getValue());
        tenantUserDO.setModifyBy(UserUtils.getUserId());
        tenantUserDO.setModifyTime(LocalDateTime.now());
        return getBean().modifyData(tenantUserDO, null, false);
    }

    @Override
    public LoginUserDTO queryAccountLogin(AccountLoginQuery query) {
        LoginUserDTO result = new LoginUserDTO();
        result.setLock(true);
        result.setJob(false);
        List<TenantUserPO> tenantUserPos = selectAllByMobile(query.getMobile());
        if (Collections3.isEmpty(tenantUserPos)) {
            return result;
        }
        List<TenantUserPO> users = tenantUserPos.stream()
                .filter(s -> PublishStatusEnum.ENABLE.getValue().equals(s.getPublishStatus()))
                .filter(s -> PublishStatusEnum.ENABLE.getValue().equals(s.getJob()))
                .collect(Collectors.toList());
        TenantUserPO tenantUserPO;
        if (Collections3.isEmpty(users)) {
            tenantUserPO = tenantUserPos.get(0);
        } else {
            tenantUserPO = users.get(0);
        }

        result = BeanUtil.convertBean(tenantUserPO, LoginUserDTO.class);
        result.setLock(!PublishStatusEnum.ENABLE.getValue().equals(tenantUserPO.getPublishStatus()));
        result.setJob(PublishStatusEnum.ENABLE.getValue().equals(tenantUserPO.getJob()));
        result.setLoginRole(LoginRoleEnum.TENANT.name());
        result.setIds(users.stream().map(s -> Long.valueOf(String.valueOf(s.getTenantId()))).collect(Collectors.toList()));
        Integer tenantId = tenantUserPO.getTenantId();
        if(tenantId!=null) {
            TenantDTO tenantDTO = queryTenantById(tenantId);
            if(tenantDTO != null){
                result.setIndustry(tenantDTO.getIndustry());
            }
        }
        LogUtils.info("LoginUserDTO >>>{}", JsonUtils.toJsonStr(result));
        return result;
    }

    @Override
    public TenantUserDTO queryByMobile(String mobile) {
        List<TenantUserPO> tenantUserPos = selectAllByMobile(mobile);
        if (Collections3.isEmpty(tenantUserPos)) {
            TenantUserDTO result = new TenantUserDTO();
            result.setId(GenerateId.generateId());
            result.setUserCode(mobile);
            result.setPassword(passwordEncoder.encode(userConfigProp.getInitialPwd()));
            result.setImage(DefaultPathConstant.DEFAULT_USER_HEAD_IMAGE);
            result.setMobile(mobile);
            result.setTel("");
            result.setEmail("");
            result.setSex(SexEnum.UNKNOWN.getCode());
            return result;
        }
        TenantUserPO tenantUserPO = tenantUserPos.get(0);
        return BeanUtil.convertBean(tenantUserPO, TenantUserDTO.class);
    }

    @Override
    public List<TenantUserDTO> queryByTenantId(Integer tenantId) {
        List<TenantUserPO> tenantUserPos = selectAllByMobile(tenantId);
        if (Collections3.isEmpty(tenantUserPos)) return new ArrayList<TenantUserDTO>();
        return JsonUtils.jsonToList(tenantUserPos, TenantUserDTO.class);
    }

    @Override
    public List<TenantListVO> queryTenants(Long userId) {
        List<TenantUserPO> tenantUserPOS = tenantUserMapper.queryTenantPos(getTenantIds(), userId);
        if (Collections3.isEmpty(tenantUserPOS)) {
            return Collections3.emptyList();
        }
        //获取租户信息
        List<Integer> havaTenantIds = tenantUserPOS.stream().map(TenantUserPO::getTenantId).collect(Collectors.toList());
        ResponseResult<List<TenantListDTO>> responseResult = globalTenantClient.queryUserTenantsByIds(havaTenantIds);
        if (null == responseResult || Collections3.isEmpty(responseResult.getData())) {
            return Collections3.emptyList();
        }
        Map<Integer, String> tenantUserMap = tenantUserPOS.stream().collect(Collectors.toMap(TenantUserPO::getTenantId, TenantUserPO::getMobile));
        List<TenantListVO> tenantListVOS = JsonUtils.jsonToList(responseResult.getData().stream().filter(s -> PublishStatusEnum.ENABLE.getValue().equals(s.getPublishStatus())).collect(Collectors.toList()), TenantListVO.class);
        List<TenantListVO> sortedTenantListVOS = tenantListVOS.stream().sorted(Comparator.comparing(TenantListVO::getId)).collect(Collectors.toList());
        sortedTenantListVOS.forEach(x -> {
            x.setUserMobile(tenantUserMap.get(x.getId()));
            if(StringUtils.isNotEmpty(x.getIndustry())) {
                x.setIndustryName(IndustryTypeEnum.getNameByCode(x.getIndustry()));
            }
        });
        return sortedTenantListVOS;
    }

    @Override
    public CurrentUserVO currentInfo(Long id) {
        List<TenantUserDO> tenantUserDos = tenantUserMapper.queryUserById(getTenantIds(), id);
        CurrentUserVO currentUserVO = BeanUtil.convertBean(tenantUserDos.get(0), CurrentUserVO.class);
        currentUserVO.setSexName(MemberSexEnum.getDescByCode(currentUserVO.getSex()));
        currentUserVO.setImage(UrlUtils.addUrlDomainName(fileOssProp.getHost(), currentUserVO.getImage()));
        return currentUserVO;
    }

    @Override
    public Boolean del(Long userId) {
        TenantUserBO tenantUserBO = getBean().queryById(userId);
        if (PublishStatusEnum.ENABLE.getValue().equals(tenantUserBO.getJob())) {
            throw new BusinessException("请先离职后再删除");
        }
        return tenantUserMapper.deleteById(userId) > 0;
    }

    @Override
    public Boolean findPwd(UserFindPwdParam userFindPwdParam) {
        List<TenantUserPO> tenantUserPos = tenantUserMapper.selectAllByMobile(getTenantIds(), userFindPwdParam.getPhone());
        if (Collections3.isEmpty(tenantUserPos)) {
            LogUtils.warn(LogClassifyEnum.OPERATION_LOG, "用户[{}]不存在", userFindPwdParam.getPhone());
            return false;
        }
        TenantUserPO tenantUserPO = tenantUserPos.get(0);
        if (PublishStatusEnum.DISABLE.getValue().equals(tenantUserPO.getPublishStatus())) {
            throw new BusinessException("账号已锁定");
        }
        ResponseResult<String> responseResult = msgClient.queryVerificationCode(userFindPwdParam.getKey(), userFindPwdParam.getPhone());
        if (StringUtils.isBlank(responseResult.getData())) {
            throw new BusinessException("验证码已过期");
        }
        if (!userFindPwdParam.getVerificationCode().equals(responseResult.getData())) {
            throw new BusinessException("验证码错误");
        }
        String newPwd;
        try {
            newPwd = EncryptUtils.RsaEncrypt.decrypt(userFindPwdParam.getNewPassword(), rsaConfig.getKeyPair().getPrivate());
        } catch (Exception e) {
            throw new EncryptException("密码非用户输入密码");
        }
        return getBean().modifyPassword(tenantUserPO.getId(), newPwd);
    }

    @Override
    public Boolean resetPwd(Long id) {
        return getBean().modifyPassword(id, "");
    }

    @Override
    public Boolean modifyPwd(Long userId, UserModifyPwdParam userModifyPwdParam) {
        TenantUserBO tenantUserBO = getBean().queryById(userId);
        String oldPwd;
        String newPwd;
        try {
            oldPwd = EncryptUtils.RsaEncrypt.decrypt(userModifyPwdParam.getOldPassword(), rsaConfig.getKeyPair().getPrivate());
            newPwd = EncryptUtils.RsaEncrypt.decrypt(userModifyPwdParam.getNewPassword(), rsaConfig.getKeyPair().getPrivate());
        } catch (Exception e) {
            throw new EncryptException("密码非用户输入密码");
        }
        if (!passwordEncoder.matches(oldPwd, tenantUserBO.getPassword())) {
            throw new BusinessException("旧密码错误");
        }
        return getBean().modifyPassword(userId, newPwd);
    }

    @Override
    public Boolean modifyPassword(Long userId, String newPassword) {
        TenantUserDO tenantUserDO = new TenantUserDO();
        tenantUserDO.setId(userId);
        tenantUserDO.setModifyTime(LocalDateTime.now());
        tenantUserDO.setPassword(StringUtils.isEmpty(newPassword) ? passwordEncoder.encode(userConfigProp.getInitialPwd()) : passwordEncoder.encode(newPassword));
        return getBean().modifyData(tenantUserDO, null, true);
    }

    @Override
    public List<String> queryRoleIdsByUserId(Long userId) {
        List<TenantUserRoleBO> userRoleBos = userRoleServiceImpl.queryUserRoleByUserId(userId);
        if (Collections3.isEmpty(userRoleBos)) {
            return Collections3.emptyList();
        }
        return userRoleBos.parallelStream().map(userRoleBO -> String.valueOf(userRoleBO.getRoleId())).distinct().collect(Collectors.toList());
    }

    @Override
    public UserInfoDTO queryLoginUser(Long userId, Integer tenantId) {
        TenantUserBO tenantUserBO = getBean().queryById(userId);
        UserInfoDTO userInfoDTO = BeanUtil.convertBean(tenantUserBO, UserInfoDTO.class);
        List<TenantUserRoleBO> tenantUserRoleBOS = userRoleServiceImpl.queryUserRoleByUserId(userId);
        userInfoDTO.setRoleIds(tenantUserRoleBOS.parallelStream().map(TenantUserRoleBO::getRoleId).collect(Collectors.toList()));
        userInfoDTO.setLoginRole(LoginRoleEnum.TENANT);
        if(tenantId!=null) {
            TenantDTO tenantDTO = queryTenantById(tenantId);
            if(tenantDTO != null){
                userInfoDTO.setIndustry(tenantDTO.getIndustry());
                userInfoDTO.setTenantId(tenantId);
            }
        }
        return userInfoDTO;
    }

    @Override
    public Boolean modifySelf(Long userId, TenantUserParam param) {
        TenantUserDO tenantUserDO = new TenantUserDO();
        tenantUserDO.setId(userId);
        tenantUserDO.setName(param.getName());
        tenantUserDO.setNickName(param.getNickName());
        tenantUserDO.setSex(param.getSex());
        tenantUserDO.setImage(param.getImage());
        tenantUserDO.setTel(param.getTel());
        tenantUserDO.setEmail(param.getEmail());
        tenantUserDO.setDescription(param.getDescription());
        tenantUserDO.setModifyTime(LocalDateTime.now());
        return getBean().modifyData(tenantUserDO, null, true);
    }

    @CacheEvict(cacheName = RedisKeyConstant.MODULE_B + RedisKeyConstant.USER_INFO, key = "#tenantUserDO.id")
    @Override
    public Boolean modifyData(TenantUserDO tenantUserDO, List<Integer> tenantIds, Boolean all) {
        tenantUserDO.setModifyTime(LocalDateTime.now());
        if (all) {
            if (Collections3.isEmpty(tenantIds)) {
                List<TenantUserPO> tenantUserPos = selectAllById(tenantUserDO.getId());
                tenantIds = tenantUserPos.stream().map(TenantUserPO::getTenantId).collect(Collectors.toList());
            }
            for (Integer tenantId : tenantIds) {
                getBean().updateAll(tenantId, tenantUserDO);
            }

        } else {
            tenantUserMapper.updateById(tenantUserDO);
        }
        return true;
    }

    @Override
    public Boolean updateAll(Integer tenantId, TenantUserDO tenantUserDO) {
        tenantUserDO.setModifyTime(LocalDateTime.now());
        return tenantUserMapper.updateAll(tenantUserDO, tenantId) > 0;
    }

    @Override
    public Boolean modifyMobile(Long userId, ModifyMobileParam param) {
        ResponseResult<Boolean> responseResult = msgClient.checkVerificationCode(param.getKey(), param.getMobile(), param.getVerificationCode());
        if (null == responseResult || null == responseResult.getData() || !responseResult.getData()) {
            throw new BusinessException("验证码错误或已过期");
        }
        TenantUserDO tenantUserDO = new TenantUserDO();
        tenantUserDO.setId(userId);
        tenantUserDO.setMobile(param.getMobile());
        tenantUserDO.setModifyTime(LocalDateTime.now());
        return getBean().modifyData(tenantUserDO, null, true);
    }

    @Override
    public List<TenantUserPO> queryByMobiles(List<String> mobiles) {
        List<Integer> tenantIds = getTenantIds();
        return tenantUserMapper.selectAllByMobiles(tenantIds, mobiles);
    }

    @Override
    public Boolean phoneCodeCheck(String phone, String verificationCode, String key) {
        if (Objects.equals(verificationCode, "202102")) {
            //todo 临时测试用code
            return true;
        }
        if (StringUtils.isBlank(key)) {
            throw BusinessException.create("验证码发送凭证不能为空!");
        }
        Boolean res = Optional.ofNullable(msgClient.checkVerificationCode(key, phone, verificationCode)).map(ResponseResult::getData).orElse(false);
        if (!res) {
            throw BusinessException.create("手机验证码错误!");
        }
        return true;
    }

    private List<TenantUserPO> selectAllByMobile(String mobile) {
        List<Integer> tenantIds = getTenantIds();
        List<TenantUserPO> tenantUserPos = tenantUserMapper.selectAllByMobile(tenantIds, mobile);
        if (Collections3.isEmpty(tenantUserPos)) {
            return Collections3.emptyList();
        }
        return tenantUserPos;
    }

    private List<TenantUserPO> selectAllByMobile(Integer tenantId) {
        List<TenantUserPO> tenantUserPos = tenantUserMapper.selectAllUsersByTenantId(tenantId);
        if (Collections3.isEmpty(tenantUserPos)) {
            return Collections3.emptyList();
        }
        return tenantUserPos;
    }

    private List<TenantUserPO> selectAllById(Long userId) {
        List<Integer> tenantIds = getTenantIds();
        List<TenantUserPO> tenantUserPos = tenantUserMapper.selectAllById(tenantIds, userId);
        if (Collections3.isEmpty(tenantUserPos)) {
            return Collections3.emptyList();
        }
        return tenantUserPos;
    }

    private ITenantUserService getBean() {
        return SpringBeanUtil.getBean(ITenantUserService.class);
    }

    private List<Integer> getTenantIds() {
        ResponseResult<List<Integer>> responseResult = globalClient.queryTenantIds();
        if (null == responseResult || Collections3.isEmpty(responseResult.getData())) {
            throw new BusinessException("租户不存在");
        }
        return responseResult.getData();
    }


    private TenantDTO queryTenantById(Integer tenantId) {
        ResponseResult<TenantDTO> responseResult = globalClient.queryTenantById(tenantId);
        if (null == responseResult || null == responseResult.getData()) {
            throw new BusinessException("租户不存在");
        }
        return responseResult.getData();
    }
}
